.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "JSON" "1" "July 2012" "" "json tool manual"
.
.SH "NAME"
\fBjson\fR \- (aka "jsontool") JSON love for your command line\.
.
.SH "SYNOPSIS"
something\-generating\-JSON\-on\-stdout | \fBjson\fR [OPTIONS] [LOOKUPS]
.
.P
\fBjson\fR \-f FILE [OPTIONS] [LOOKUPS\.\.\.]
.
.SH "DESCRIPTION"
Pipe in your JSON for pretty\-printing, JSON validation, filtering, and modification\. Supply one or more \fBLOOKUPS\fR to extract a subset of the JSON\. HTTP header blocks are skipped by default\.
.
.SS "Grouping"
(Added in json v4\.) Use \'\-g\' or \'\-\-group\' to group objects (into an array of objects) or concatenate arrays (into a single array) separated by no space or by a newline\. This can be helpful for, e\.g\.:
.
.IP "" 4
.
.nf

$ cat *\.json | json \-g \.\.\.
.
.fi
.
.IP "" 0
.
.P
and similar\.
.
.P
In json v3 and earlier, this used to be called "auto\-arrayification" and was implicit\. See the \fICOMPATIBILITY\fR section below\.
.
.SS "Merging"
(Added in json v4\.) Use \'\-\-merge\' or \'\-\-deep\-merge\' to merge adjacent JSON objects in the input\. Keys in the last object win\.
.
.IP "" 4
.
.nf

$ echo \'{"one":"un","two":"deux"}
{"one":"uno","three":"tres"}\' | json \-\-merge
{
  "one": "uno",
  "two": "deux",
  "three": "tres"
}
.
.fi
.
.IP "" 0
.
.P
This could be useful for merging multiple config files, e\.g\.:
.
.IP "" 4
.
.nf

$ cat /opt/app/etc/defaults\.json \e
    /etc/app/config\.json \e
    ~/\.app/config\.json | json \-\-merge
 \.\.\.
.
.fi
.
.IP "" 0
.
.SS "Execution"
Use the \fB\-e CODE\fR option to execute code on the input JSON\.
.
.IP "" 4
.
.nf

$ echo \'{"name":"trent","age":38}\' | json \-e \'age++\'
{
  "name": "trent",
  "age": 39
}
.
.fi
.
.IP "" 0
.
.P
If input is an array, this will automatically process each item separately\.
.
.SS "Conditional filtering"
Use the \fB\-c CODE\fR option to filter the input JSON\.
.
.IP "" 4
.
.nf

$ echo \'[{"age":38},{"age":4}]\' | json \-c \'age>21\'
[{"age":38}]
.
.fi
.
.IP "" 0
.
.P
If input is an array, this will automatically process each item separately\.
.
.SS "Lookups"
Use lookup arguments to extract particular values:
.
.IP "" 4
.
.nf

$ echo \'{"name":"trent","age":38}\' | json name
trent
.
.fi
.
.IP "" 0
.
.P
Use \fB\-a\fR for \fIarray processing\fR of lookups and \fItabular output\fR:
.
.IP "" 4
.
.nf

$ echo \'{"name":"trent","age":38}\' | json name
trent
$ echo \'[{"name":"trent","age":38},
         {"name":"ewan","age":4}]\' | json \-a name age
trent 38
ewan 4
.
.fi
.
.IP "" 0
.
.P
Integral values work for array index lookups:
.
.IP "" 4
.
.nf

$ echo \'["a", "b", "c"]\' | json 1
b
.
.fi
.
.IP "" 0
.
.P
Negative array indeces are also supported:
.
.IP "" 4
.
.nf

$ echo \'["a", "b", "c"]\' | json \-1
c
$ echo \'["a", "b", "c"]\' | json \-2
b
.
.fi
.
.IP "" 0
.
.SS "Pretty\-printing"
Output is "jsony" by default: 2\-space indented JSON with one exception, a single string value is printed without quotes\.
.
.IP "" 4
.
.nf

$ echo \'{"name": "trent", "age": 38}\' | json
{
  "name": "trent",
  "age": 38
}
.
.fi
.
.IP "" 0
.
.P
Use \fB\-o json\fR for explicit JSON, \fB\-o json\-N\fR for N\-space indent:
.
.IP "" 4
.
.nf

$ echo \'{"name": "trent", "age": 38}\' | json \-o json\-0
{"name":"trent","age":38}
.
.fi
.
.IP "" 0
.
.P
Use \fB\-H\fR to exclude a leading HTTP header block as from \fBcurl \-i\fR\.
.
.SS "Listing keys"
Sometimes you want the list of keys for an object\. Use \fB\-k\fR or \fB\-\-keys\fR for that:
.
.IP "" 4
.
.nf

$ echo \'{"name": "trent", "age": 38}\' | json \-k
[
  "name",
  "age"
]
$ echo \'{"name": "trent", "age": 38}\' | json \-ka
name
age
.
.fi
.
.IP "" 0
.
.SH "OPTIONS"
.
.TP
\fB\-h\fR, \fB\-\-help\fR
Print this help info and exit\.
.
.TP
\fB\-\-version\fR
Print version of this command and exit\.
.
.TP
\fB\-q, \-\-quiet\fR
Don\'t warn if input isn\'t valid JSON\.
.
.P
By default \fBjson\fR will process input from stdin\. Alternative, an input file (or files) can be specified:
.
.TP
\fB\-f FILE\fR
Specify an input file (instead of stdin)\.
.
.P
If your JSON output is a REST API response, it might include the headers (e\.g\. when calling with \fBcurl \-i\fR)\. By default \fBjson\fR will pass those headers through (without choking on them)\. However if you want them stripped you can use:
.
.TP
\fB\-H\fR
drop any HTTP header block (as from \fBcurl \-i \.\.\.\fR)
.
.P
Other pre\-JSON input handling:
.
.TP
\fB\-g\fR, \fB\-\-group\fR
Group adjacent objects into an array of objects, or concatenate adjacent arrays into a single array\.
.
.TP
\fB\-\-merge\fR, \fB\-\-deep\-merge\fR
Merge adjacent objects into a single object with merged keys\. Values in later objects win\. Use \fB\-\-deep\-merge\fR to recursively merge keys in objects\.
.
.P
You can process elements of an input array separately and generate tabular output:
.
.TP
\fB\-a\fR, \fB\-\-array\fR
Process input as an array of separate inputs and output in tabular form\.
.
.TP
\fB\-d DELIM\fR
Delimiter character for tabular output (default is \' \')\.
.
.TP
\fB\-A\fR
Process input as a single object, i\.e\. stop \fB\-e\fR and \fB\-c\fR automatically processing each item of an input array\.
.
.P
You can execute code on (\fB\-e\fR) and filter (\fB\-c\fR) the input (this is done before LOOKUPS are processed, if any)\. If datum is an object, then a shortcut is \fB<key>\fR\. To remove a key, use \fBthis\.<key> = undefined\fR\. For array items, use \fBthis[<index>] = 42\fR\.
.
.TP
\fB\-e CODE\fR
Execute the given code on the input\. If input is an array, then each item of the array is processed separately (use \fB\-A\fR to override)\.
.
.TP
\fB\-c CODE\fR
Filter the input with \fBCODE\fR\. If \fBCODE\fR returns false\-y, then the item is filtered out\. If input is an array, then each item of the array is processed separately (use \fB\-A\fR to override)\.
.
.P
Finally, if \fBLOOKUP\fR arguments are given, these are extracted from the JSON\. By default \fB\.\fR is used as a separator for nested object lookup\. This can be overridden:
.
.TP
\fB\-D DELIM\fR
Delimiter char between LOOKUPS (default is \'\.\')\. For example: \fB$ echo \'{"a\.b": {"b": 1}}\' | json \-D / a\.b/b\fR
.
.P
An alternative to lookups is to output the keys of the input object:
.
.TP
\fB\-k\fR, \fB\-\-keys\fR
Output the input object\'s keys\.
.
.P
\fBjson\fR can be restricting to just validating its input, i\.e\. processing and output of the input is skipped:
.
.TP
\fB\-\-validate\fR
Just validate the input, no processing or output of the JSON content\.
.
.P
By default \fBjson\fR outputs in "jsony" mode\. Basically this is JSON output, with the exception that a single string output value is emitted without the quotes\. The intention here is to be of most use to the UNIX command\-line\. Other output formats are supported:
.
.TP
\fB\-o MODE\fR, \fB\-\-output MODE\fR
Specify an output mode\. One of \fBjsony\fR (the default; JSON, if a single string then quotes are elided), \fBjson\fR (JSON output, 2\-space indent), \fBjson\-N\fR (JSON output, N\-space indent, e\.g\. \'json\-4\'), or \fBinspect\fR (node\.js \fButil\.inspect\fR output)\.
.
.TP
\fB\-i\fR
Shortcut for \fB\-o inspect\fR\.
.
.TP
\fB\-j\fR
Shortcut for \fB\-o json\fR\.
.
.SH "EXAMPLES"
A typical JSON REST API response:
.
.IP "" 4
.
.nf

$ curl \-s http://ifconfig\.me/all\.json
{"connection":"","ip_addr":"216\.57\.203\.67","lang":"","remote_host":\.\.\.
.
.fi
.
.IP "" 0
.
.P
\fBNice output by default\fR:
.
.IP "" 4
.
.nf

$ curl \-s http://ifconfig\.me/all\.json | json
{
  "connection": "",
  "ip_addr": "201\.73\.103\.12",
  "lang": "",
  "remote_host": "",
  "user_agent": "curl/7\.23\.1 (i386\-sun\-solaris2\.11) libcurl/7\.23\.1 OpenSSL/0\.9\.8w zlib/1\.2\.3 libidn/1\.23 libssh2/1\.2\.2",
  "charset": "",
  "port": "63713",
  "via": "",
  "forwarded": "",
  "mime": "*/*",
  "keep_alive": "",
  "encoding": ""
}
.
.fi
.
.IP "" 0
.
.P
Say you just want to \fBextract one value\fR:
.
.IP "" 4
.
.nf

$ curl \-s http://ifconfig\.me/all\.json | json ip_addr
201\.73\.103\.12
.
.fi
.
.IP "" 0
.
.P
Or, looking at the node\.js project \fIhttps://github\.com/joyent/node\fR using the Github API:
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/repos/joyent/node | json open_issues
517
.
.fi
.
.IP "" 0
.
.P
If you use \fBcurl \-i\fR to get HTTP headers (because perhaps they contain relevant information), \fBjson will skip the HTTP headers automatically\fR:
.
.IP "" 4
.
.nf

$ curl \-is https://api\.github\.com/repos/joyent/node | json
HTTP/1\.1 200 OK
Server: nginx/1\.0\.13
Date: Tue, 24 Jul 2012 04:01:08 GMT
Content\-Type: application/json; charset=utf\-8
Connection: keep\-alive
Status: 200 OK
ETag: "1a21d980a01768dde42145ce2b58694c"
X\-RateLimit\-Remaining: 4997
Content\-Length: 1513
Cache\-Control: public, max\-age=60
Vary: Accept
X\-RateLimit\-Limit: 5000
Last\-Modified: Tue, 24 Jul 2012 03:50:11 GMT

{
  "master_branch": "master",
  "has_issues": true,
  "has_downloads": false,
  "homepage": "http://nodejs\.org/",
  "html_url": "https://github\.com/joyent/node",
 \.\.\.
.
.fi
.
.IP "" 0
.
.P
Or, say you are stuck with the headers in your pipeline, \fB\'json \-H\' will drop HTTP headers\fR:
.
.IP "" 4
.
.nf

$ curl \-is https://api\.github\.com/repos/joyent/node | json \-H forks
2158
.
.fi
.
.IP "" 0
.
.P
Here is \fBan example that shows indexing a list\fR\. (The given "lookup" argument is basically JavaScript code appended, with \'\.\' if necessary, to the JSON data and eval\'d\.)
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/legacy/repos/search/nodejs \e
    | json \'repositories[2]\.name\'
socket\.io
.
.fi
.
.IP "" 0
.
.P
Having the quote to avoid shell interpretation of \'[\' is annoying, so \fBjson\fR allows a special case for an integer lookup:
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/legacy/repos/search/nodejs \e
    | json \'repositories\.2\.name\'
socket\.io
.
.fi
.
.IP "" 0
.
.SS "Array processing with \-a"
\fBjson\fR includes the \fB\-a\fR (aka \fB\-\-array\fR) option for \fBprocessing each element of an input JSON array independently\fR and \fBusing tabular output\fR\. Let\'s first get a list of open node\.js issues (note that this is a subset because of GH API pagination \fIhttp://developer\.github\.com/v3/#pagination\fR):
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/repos/joyent/node/issues?state=open\e&per_page=100
[
  {
    "number": 3757,
    "html_url": "https://github\.com/joyent/node/issues/3757",
    "body": "Fix #3756\.\en\enReview, please: @TooTallNate",
    "milestone": null,
    "user": {
      "gravatar_id": "73a2b24daecb976af81e010b7a3ce3c6",
      "login": "isaacs",
      "avatar_url": "https://secure\.gravatar\.com/avatar/73a2b24dae\.\.\.
 \.\.\.
.
.fi
.
.IP "" 0
.
.P
We can then print a table with just some fields as follows:
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/repos/joyent/node/issues?state=open\e&per_page=100 \e
    | json \-a comments number title
0 3757 readline: Remove event listeners on close
0 3756 readline: No way to completely unhook interface from input/output
1 3755 node\-v0\.6\.20 hello example segfaults on RaspberryPi (w/Arch + bash)
0 3753 Prohibit same listeners in EventEmitter\. Closes #964\.
1 3752 Auto\-detect hardfloat eabi and armv7 variables on ARM based on compiler
3 3751 persistent REPL history
0 3749 glibc errors on SheevaPlug / Debian Squeeze
 \.\.\.
.
.fi
.
.IP "" 0
.
.P
Ultimately this can be useful for then using other command\-line tools\. For example, we could get the list of top\-five most commented open node issues:
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/repos/joyent/node/issues?state=open\e&per_page=100 \e
    | json \-a comments number title | sort \-n  | tail \-5
9 3510 Automatically `\.toString()` functions in REPL\.
11 3668 JSON documentation index listing
12 3624 Add a return value to Buffer\.write* methods that returns the \.\.\.
12 3655 defer dgram listening event
14 3613 Connections closed by node stay permanently in FIN_WAIT2
.
.fi
.
.IP "" 0
.
.P
Or get a breakdown by ISO language code of the recent tweets mentioning "nodejs":
.
.IP "" 4
.
.nf

$ curl \-s http://search\.twitter\.com/search\.json?q=nodejs\e&rpp=100 \e
    | json results | json \-a iso_language_code | sort | uniq \-c | sort
   1 es
   1 no
   1 th
   4 ru
  12 ja
  23 pt
  58 en
.
.fi
.
.IP "" 0
.
.P
The \fB\fB\-d\fR option can be used to specify a delimiter\fR:
.
.IP "" 4
.
.nf

$ curl \-s https://api\.github\.com/repos/joyent/node/issues?state=open \e
        | json \-a created_at number title \-d,
2012\-07\-24T03:45:03Z,3757,readline: Remove event listeners on close
2012\-07\-24T03:32:10Z,3756,readline: No way to completely unhook inte\.\.\.
2012\-07\-23T21:17:50Z,3755,node\-v0\.6\.20 hello example segfaults on Ra\.\.\.
2012\-07\-22T16:17:49Z,3753,Prohibit same listeners in EventEmitter\. C\.\.\.
2012\-07\-22T13:43:40Z,3752,Auto\-detect hardfloat eabi and armv7 varia\.\.\.
.
.fi
.
.IP "" 0
.
.SS "Grouping"
You can use the \fB\'\-g\' or \'\-\-group\' option to group adjacent objects\fR into an array of those objects; or to concatenate adjacent arrays into a single array\. To attempt to avoid false positives inside JSON strings, \fIadjacent\fR elements must have either no whitespace separation or at least a newline separation\. Examples:
.
.IP "" 4
.
.nf

$ echo \'{"a":1}{"b":2}\' | json \-g       # group into array of objects
[
  {
    "a": 1
  },
  {
    "b": 2
  }
]
$ echo \'[1,2][3,4]\' | json \-g           # concantenate into one array
[
  1,
  2,
  3,
  4
]
.
.fi
.
.IP "" 0
.
.P
This can be useful when processing a number of JSON files, e\.g\.:
.
.IP "" 4
.
.nf

$ cat my_data/*\.json | json \-g \.\.\.
.
.fi
.
.IP "" 0
.
.P
Or when composing multiple JSON API response, e\.g\. this somewhat contrived search for node\.js bugs mentioning "tty" or "windows":
.
.IP "" 4
.
.nf

$ echo tty windows | xargs \-n1 \-I{} curl \-s \e
    https://api\.github\.com/legacy/issues/search/joyent/node/open/{} \e
    | json \-g \-a issues | json \-g \-a number title
623 Non\-userfacing native modules should be prefixed with _
861 child_process fails after stdin close
1157 `child_process` module should read / write password prompts
1180 Ctrl+Shift+BS can\'t be input\.
 \.\.\.
.
.fi
.
.IP "" 0
.
.SS "Output formatting"
You can use the \'\-o MODE\' option (or \'\-\-output MODE\') to control the output flavour\. By default the output is "jsony" (JSON, except that a simple string is printed \fIwithout the quotes\fR):
.
.IP "" 4
.
.nf

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json
[
  {
    "name": "Trent"
  },
  {
    "name": "Ewan"
  }
]

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json \'0\.name\'
Trent

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json \'0\.name\' \-o jsony
Trent
.
.fi
.
.IP "" 0
.
.P
Or for strict JSON output:
.
.IP "" 4
.
.nf

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json \-o json
[
  {
    "name": "Trent"
  },
  {
    "name": "Ewan"
  }
]
.
.fi
.
.IP "" 0
.
.P
By default this uses a 2\-space indent\. That can be changed with a "\-N" suffix:
.
.IP "" 4
.
.nf

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json \-o json\-4
[
    {
        "name": "Trent"
    },
    {
        "name": "Ewan"
    }
]

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json \-o json\-0
[{"name":"Trent"},{"name":"Ewan"}]
.
.fi
.
.IP "" 0
.
.P
You can get colored (non\-JSON) output using node\.js\'s \fButil\.inspect\fR \fIhttp://nodejs\.org/docs/latest/api/all\.html#util\.inspect\fR:
.
.IP "" 4
.
.nf

$ echo \'[{"name": "Trent"},{"name": "Ewan"}]\' | json \-o inspect
[ { name: \'Trent\' },
  { name: \'Ewan\' } ]
.
.fi
.
.IP "" 0
.
.SS "Validation"
Since v1\.2\.0 \fBjson\fR will give position information and context for JSON syntax errors (\fBSyntaxError\fR)\. This can be handy for validating data and config files:
.
.IP "" 4
.
.nf

$ cat config\.json | json
json: error: input is not JSON: Unexpected \',\' at line 17, column 5:
            , { "name": "smartos64\-1\.4\.7"
        \.\.\.\.^
{
    "use\-proxy": false
 \.\.\.
$ echo $?
1
.
.fi
.
.IP "" 0
.
.P
Processing and output of the input JSON can be suppressed with the \fB\-\-validate\fR option:
.
.IP "" 4
.
.nf

$ cat config\.json | json \-\-validate
json: error: input is not JSON: Unexpected \',\' at line 17, column 5:
            , { "name": "smartos64\-1\.4\.7"
        \.\.\.\.^
.
.fi
.
.IP "" 0
.
.P
Together with the \fB\-q\fR you can get silent, exit\-status\-only, JSON validation:
.
.IP "" 4
.
.nf

$ cat config\.json | json \-\-validate \-q
$ echo $?
1
.
.fi
.
.IP "" 0
.
.SS "Executing code snippets on input"
You can use the \fB\-e CODE\fR option to execute small code snippets to massage the input data\. Some examples (generally use \fBthis\.<key>\fR to refer to a key):
.
.IP "" 4
.
.nf

$ echo \'{"foo": "bar"}\' | json \-e \'this\.foo="baz"\'
{"foo":"baz"}
.
.fi
.
.IP "" 0
.
.P
Or omit the \fBthis\.\fR as a shortcut:
.
.IP "" 4
.
.nf

$ echo \'{"foo": "bar"}\' | json \-e \'foo="baz"\'
{"foo":"baz"}
$ echo \'{"age": 38}\' | json \-e \'age++\'
{"age":39}
.
.fi
.
.IP "" 0
.
.P
Set a key to \fBundefined\fR to remove it:
.
.IP "" 4
.
.nf

$ echo \'{"one": 1, "two": 2}\' | json \-e \'this\.one=undefined\'
{"two":2}
.
.fi
.
.IP "" 0
.
.P
If the input is an array, then \fB\-e\fR will automatically process each element separately (use \fB\-A\fR to override this):
.
.IP "" 4
.
.nf

$ echo \'[{"name":"trent", "age":38}, {"name":"ewan", "age":4}]\' \e
    | json \-e \'age++\'
[
  {
    "name": "trent",
    "age": 39
  },
  {
    "name": "ewan",
    "age": 5
  }
]
.
.fi
.
.IP "" 0
.
.SS "Filtering with \'\-c\'"
You can use the \fB\-c CODE\fR option to filter the input:
.
.IP "" 4
.
.nf

$ echo \'{"name":"trent", "age":38}\' | json \-c \'age>21\'
{
  "name": "trent",
  "age": 38
}
$ echo \'{"name":"trent", "age":38}\' | json \-c \'age==16\'
$
.
.fi
.
.IP "" 0
.
.P
If the input is an array, then \fB\-c\fR will automatically process each element separately (use \fB\-A\fR to override this):
.
.IP "" 4
.
.nf

$ echo \'[{"name":"trent", "age":38}, {"name":"ewan", "age":4}]\' \e
    | json \-c \'age>21\'
[
  {
    "name": "trent",
    "age": 38
  }
]
.
.fi
.
.IP "" 0
.
.SH "COMPATIBILITY"
This is json version 4\. The major version is incremented when there is a backward incompatible change\.
.
.IP "\(bu" 4
v4: Made "auto\-arrayification" require an explicit \'\-g\' or \'\-\-group\' option to prefer that implicit processing never magically fix otherwise invalid JSON\. The feature is now called grouping\.
.
.IP "\(bu" 4
v3: Cleaned up json and "jsony" output formatting to be more consistent, especially for array processing\.
.
.IP "" 0
.
.P
See the changelog \fIhttps://github\.com/trentm/json/blob/master/CHANGES\.md\fR for full compatibility and change details\.
.
.SH "PROJECT & BUGS"
\fBjson\fR is written in JavaScript and requires node\.js (\fBnode\fR)\. The project lives at \fIhttps://github\.com/trentm/json\fR and is published to npm as "jsontool" ("json" was already taken, boo)\.
.
.IP "\(bu" 4
README, Install notes: \fIhttps://github\.com/trentm/json#readme\fR
.
.IP "\(bu" 4
Report bugs to \fIhttps://github\.com/trentm/json/issues\fR\.
.
.IP "\(bu" 4
See the full changelog at: \fIhttps://github\.com/trentm/json/blob/master/CHANGES\.md\fR
.
.IP "" 0
.
.SH "LICENSE"
MIT License (see \fIhttps://github\.com/trentm/json/blob/master/LICENSE\.txt\fR)
.
.SH "COPYRIGHT"
json is Copyright (c) 2012 Trent Mick
